package com.elitecrm.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPReply;


public class FTPUtil {
	private static final Log log=LogFactory.getLog(FTPUtil.class);
	
	private FTPClient ftpClient=null;
	
	public FTPUtil(String hostName,String loginName,String password,int port) throws Exception{	
		this.ftpClient=createFTPClient(hostName,loginName,password,port);
	}
	public FTPUtil(String hostName,String loginName,String password,int port,String characterEncoding) throws Exception{	
		this.ftpClient=createFTPClient(hostName,loginName,password,port,characterEncoding);
	}
	
	private FTPClient createFTPClient(String hostName,String loginName,String password,int port)  throws Exception{
		String characterEncoding="utf-8";
		return createFTPClient(hostName,loginName,password,port,characterEncoding);
	}
	private FTPClient createFTPClient(String hostName,String loginName,String password,int port,String characterEncoding) throws Exception{
		
		FTPClient ftpClient=new FTPClient();
		ftpClient.connect(hostName,port);
		ftpClient.setControlEncoding(characterEncoding);
		FTPClientConfig config=new FTPClientConfig(FTPClientConfig.SYST_NT);
		config.setServerLanguageCode("zh");
		ftpClient.configure(config);
		ftpClient.login(loginName, password);
		if(!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){
			ftpClient.disconnect();
			return null;
		}
		return ftpClient;
	}
	public List<String> listFileNames(String remoteDir) throws Exception{
		if(ftpClient!=null && ftpClient.isConnected()){
			String[] namesArr=ftpClient.listNames(remoteDir);
			List<String> namesTemp=Arrays.asList(namesArr);
			List<String> names=new ArrayList<String>(namesTemp);
			return names;
		}
		return null;
	}
	/**
	 * download the file from ftp server
	 * @param remotePath: remote file name which need to be download
	 * @param downloadPath:the path on the server that the remote file save to
	 * @return the path of the download file on the server
	 */
	public String download(String remotePath,String downloadPath){
		String fileNameWithSuffix= parseFileNameWithSuffix(remotePath);
		if(ftpClient!=null && ftpClient.isConnected()){
			FileOutputStream out = null;
			try{
				String fPath=utf8ToIso8859(remotePath);
				//设置被动模式
				ftpClient.enterLocalPassiveMode();
				//检查远程文件是否存在
				String[] names = ftpClient.listNames(fPath);
				if(names==null || names.length <0){
					log.error(remotePath+":"+FTPStatus.REMOTE_FILE_NOT_EXIST);
					return null;
				}else{
					log.info(fPath+":"+names.length);
				}
				//设置以二进制方式传输
				ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
				String fileName=parseFileName(fileNameWithSuffix);
				File folder=new File(downloadPath+"/"+fileName);
				if(folder.exists()){
					if(true){//Config.isDeleteIfExist()
						deleteFile(folder);
					}else{
						return folder.getPath()+"/"+fileNameWithSuffix;
					}
				}
				folder.mkdirs();		
				File f=new File(folder.getPath()+"/"+fileNameWithSuffix);	
				out = new FileOutputStream(f,true);
				boolean flag = ftpClient.retrieveFile(fPath, out);
				if(flag){
					log.info(fileNameWithSuffix+":"+FTPStatus.DOWNLOAD_FILE_SUCCESS);
					return folder.getPath()+"/"+fileNameWithSuffix;
				}
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				if(out!=null){try {out.close();} catch (IOException e) {}}
				if(ftpClient!=null && ftpClient.isConnected()){try{ftpClient.disconnect();}catch(Exception e){e.printStackTrace();}}
			}
		}else{
			log.error(fileNameWithSuffix+":"+FTPStatus.FTP_NOT_CONNECT);
		}
		log.error(fileNameWithSuffix+":"+FTPStatus.DOWNLOAD_FILE_FAILURE);
		return null;
	}
	/**
	 * 上传回复的目标文件到ftp server
	 * @param emlPath:本地需要上传的eml文件路径
	 * @param uploadFolderPath:上传到ftp server上的目录路径
	 */
	public boolean upload(String targetPath,String uploadFolderPath){
		if(ftpClient!=null && ftpClient.isConnected()){
			FileInputStream fis=null;
			File targetFile=new File(targetPath);
			try {
				fis=new FileInputStream(targetFile);
				ftpClient.enterLocalPassiveMode();
				ftpClient.setFileType(FTP.BINARY_FILE_TYPE); 
				FTPStatus status=createDirecroty(uploadFolderPath,ftpClient);
				if(status.equals(FTPStatus.CREATE_DIRECTORY_FAIL)){
					log.error(FTPStatus.CREATE_DIRECTORY_FAIL+":"+uploadFolderPath+", please check the ftp RW right.");
					return false;
				}
				
				//boolean changeSuccess=ftpClient.changeWorkingDirectory(utf8ToIso8859(uploadFolderPath));
				//if(changeSuccess){
					String name=targetFile.getName();
					boolean flag=ftpClient.storeFile(utf8ToIso8859(name), fis);
					if(flag){
						log.info(targetPath+":"+FTPStatus.UPLOAD_FILE_SUCCESS);
						return true;
					}else{
						log.error(targetPath+":"+FTPStatus.UPLOAD_FILE_FAILURE);
						return false;
					}
				//}else{
				//	log.error("change working directory failure");
				//	return false;
				//}
			} catch (Exception e) {
				e.printStackTrace();
				log.error(targetPath+":"+FTPStatus.UPLOAD_FILE_FAILURE);
				return false;
			}finally{
				if(fis!=null){try {fis.close();} catch (IOException e) {}}
				if(ftpClient!=null && ftpClient.isConnected()){try {ftpClient.disconnect();} catch (IOException e) {}}
			}
		}else{
			log.error(targetPath+":"+FTPStatus.FTP_NOT_CONNECT);
			return false;
		}		
	}
	public boolean upload(InputStream is,String fileName,String uploadFolderPath){
		if(ftpClient!=null && ftpClient.isConnected()){
			try {
				ftpClient.enterLocalPassiveMode();
				ftpClient.setFileType(FTP.BINARY_FILE_TYPE); 
				FTPStatus status=createDirecroty(uploadFolderPath,ftpClient);
				if(status.equals(FTPStatus.CREATE_DIRECTORY_FAIL)){
					log.error(FTPStatus.CREATE_DIRECTORY_FAIL+":"+uploadFolderPath+", please check the ftp RW right.");
					return false;
				}	
				boolean flag=ftpClient.storeFile(utf8ToIso8859(fileName), is);
				if(flag){
					log.info(fileName+":"+FTPStatus.UPLOAD_FILE_SUCCESS);
					return true;
				}else{
					log.error(fileName+":"+FTPStatus.UPLOAD_FILE_FAILURE);
					return false;
				}
			} catch (Exception e) {
				e.printStackTrace();
				log.error(fileName+":"+FTPStatus.UPLOAD_FILE_FAILURE);
				return false;
			}finally{
				if(ftpClient!=null && ftpClient.isConnected()){try {ftpClient.disconnect();} catch (IOException e) {}}
			}
		}else{
			log.error(fileName+":"+FTPStatus.FTP_NOT_CONNECT);
			return false;
		}		
	}
	
	 public FTPStatus createDirecroty(String remote,FTPClient ftpClient) throws IOException{  
			FTPStatus status = FTPStatus.CREATE_DIRECTORY_SUCCESS;  
	        String directory = remote.substring(0,remote.lastIndexOf("/")+1);
	        if(!directory.equalsIgnoreCase("/")&&!ftpClient.changeWorkingDirectory(utf8ToIso8859(directory))){  
	            //如果远程目录不存在，则递归创建远程服务器目录  
	            int start=0;  
	            int end = 0;  
	            if(directory.startsWith("/")){  
	                start = 1;  
	            }else{  
	                start = 0;
	            }  
	            end = directory.indexOf("/",start);  
	            while(true){  
	                String subDirectory = utf8ToIso8859(remote.substring(start,end));  
	                if(!ftpClient.changeWorkingDirectory(subDirectory)){  
	                    if(ftpClient.makeDirectory(subDirectory)){  
	                        ftpClient.changeWorkingDirectory(subDirectory);  
	                    }else{
	                        return FTPStatus.CREATE_DIRECTORY_FAIL;  
	                    }  
	                }
	                start = end + 1;  
	                end = remote.indexOf("/",start);  
	                
	                //检查所有目录是否创建完毕  
	                if(end <= start){  
	                    break;  
	                }  
	            }  
	        }
	        return status;  
	    }  


	public FTPClient getFtpClient() {
		return ftpClient;
	}

	public void setFtpClient(FTPClient ftpClient) {
		this.ftpClient = ftpClient;
	}
	
	//得到去除文件后缀名的文件名
	public static String parseFileName(String fileName){
		if(fileName.indexOf(".")==-1){
			return null;
		}
		String[] strs = fileName.split("\\.");
		if(strs!=null && strs.length!=0){
			return fileName.substring(0, fileName.indexOf(strs[strs.length-1])-1);
		}
		return null;
	}
	
	//删除文件
	public void deleteFile(File file){
		if(file.exists()){
			if(file.isFile()){
				file.delete();
			}else if(file.isDirectory()){
				File files[] = file.listFiles();
				for(int i=0;i<files.length;i++){
					this.deleteFile(files[i]);
				}
			}
			file.delete();
			log.debug("delete file success");
		}else{
			log.debug("delete file not exist!");
		}
	} 
	
	public void disconnect() throws IOException{  
	     if(ftpClient!=null && ftpClient.isConnected()){  
	    	 ftpClient.logout();
	    	 log.debug("ftp logout!");
	         ftpClient.disconnect(); 
	         log.debug("ftp disconnected!");
	     }  
	}
	
	private static String iso8859ToUtf8(Object obj) {
        try {
                if (obj == null)
                        return "";
                else
                        return new String(obj.toString().getBytes("iso-8859-1"), "utf-8");
        } catch (Exception e) {
                return "";
        }
	}
	private static String utf8ToIso8859(Object obj) {
        try {
                if (obj == null)
                        return "";
                else
                        return new String(obj.toString().getBytes("utf-8"), "iso-8859-1");
        } catch (Exception e) {
                return "";
        }
	}
	public static String parseFileNameWithSuffix(String remotePath){
		int index=remotePath.lastIndexOf("/")+1;
		String result=null;
		if(index!=-1){
			result=remotePath.substring(index,remotePath.length());
		}
		return result;
	}
	public static String checkFile(String remoteFileName,String path){
		String fileName=parseFileName(remoteFileName);
		File folder=new File(path+"/"+fileName);
		if(folder.exists()){
			
		}
		File file=new File(fileName);
		if(file.exists() && file.length()!=0){
			return fileName;
		}
		return null;
	}

}
